import 'dart:async';
import 'dart:convert';
import 'package:interrogation/src/base/utils/storage_manager.dart';
import 'package:web_socket_channel/web_socket_channel.dart';

/// WebSocket 单例连接管理器
/// 实现功能：连接管理/心跳保活/自动重连/消息分发
class IMSocket {
  static IMSocket? _instance;
  late WebSocketChannel _channel; // WebSocket通道实例
  final String _serverUrl; // WebSocket服务器地址
  final String _accessToken; // 身份认证令牌
  Timer? _heartbeatTimer; // 心跳定时器（每20秒）
  Timer? _reconnectTimer; // 重连定时器（5秒间隔）
  final _messageController = StreamController<String>.broadcast(); // 广播消息流

  /// 单例初始化工厂方法
  /// [serverUrl] 服务器地址，[accessToken] 认证令牌
  /// 首次调用时建立连接，后续调用返回现有实例
  factory IMSocket.init(String serverUrl) {
    String accessToken = StorageManager.getString(StorageConst.token) ?? "";
    _instance ??= IMSocket._internal(serverUrl, accessToken);
    return _instance!.._connect();
  }

  /// 私有构造方法，防止外部实例化
  IMSocket._internal(this._serverUrl, this._accessToken);

  /// 公开的消息流监听接口
  Stream<String> get messageStream => _messageController.stream;

  /// 建立WebSocket连接核心方法
  /// 1. 创建通道连接 2. 设置消息监听 3. 发送认证信息
  void _connect() {
    _channel = WebSocketChannel.connect(Uri.parse(_serverUrl));
    _channel.stream.listen(
      _handleMessage, // 消息处理回调
      onError: _handleError, // 错误处理回调
      onDone: _handleDisconnect, // 连接关闭回调
    );
 //   _sendAuth(); // 发送初始认证信息
    _startHeartbeat();
  }

  /// 其他cmd: 转发到消息流
  void _handleMessage(dynamic data) {
    // 心跳处理
    if ((data as String).length == 4 && data == "ping") {
      _startHeartbeat();
      return;
    }
    if ((data as String).length == 4 && data == "pong") {
      _resetHeartbeat();
      return;
    }
    final json = jsonDecode(data);
    _messageController.add(data); // 转发业务消息
  }

  /// 启动心跳定时任务
  /// 每20秒发送心跳包（cmd=1）
  void _startHeartbeat() {
    _heartbeatTimer?.cancel();
    _heartbeatTimer = Timer.periodic(Duration(seconds: 20), (_) {
      _send("ping");
    });
  }

  /// 重置心跳计时器（收到心跳响应时调用）
  void _resetHeartbeat() => _startHeartbeat();

  /// 发送初始认证信息（cmd=0）
  /// 携带_accessToken建立合法连接
  void _sendAuth() => _send(jsonEncode({
        'type': "auth",
        'content': jsonEncode({'accessToken': _accessToken})
      }));

  /// 公开消息发送接口
  /// [data] 业务消息体，封装为cmd=3格式
  void send(dynamic data) => _send(jsonEncode(data));

  /// 底层消息发送方法
  void _send(String data) => _channel.sink.add(data);

  /// 主动断开连接
  /// 1. 停止所有定时器 2. 关闭通道 3. 关闭消息流
  void disconnect() {
    _heartbeatTimer?.cancel();
    _reconnectTimer?.cancel();
    _channel.sink.close();
    _messageController.close();
  }

  /// 错误处理（网络异常/协议错误等）
  /// 5秒后尝试重新连接
  void _handleError(dynamic error) {
    _reconnectTimer = Timer(Duration(seconds: 5), _connect);
  }

  /// 连接断开处理（服务器主动关闭）
  /// 若非主动断开则触发重连
  void _handleDisconnect() => _handleError('Connection closed');
}
